package ua.com.globallogic.basecamp.krasnyanskiy.dds.list;

import java.util.Iterator;

public class SimpleList<T> implements Iterable<T> {
    private int size = 0;
    private Node<T> head;

    public void insert(T value) {
        if (head == null) {
            head = new Node<T>(head, value);
            size++;
        } else if (head.next == null) {
            head.next = new Node(null, value);
            size++;
        } else {
            getLastElement(head).next = new Node(null, value);
            size++;
        }
    }

    private Node getLastElement(Node<T> tail) {
        if (tail.next != null) {
            return getLastElement(tail.next);
        } else {
            return tail;
        }
    }

    public int size() {
        return size;
    }

    public void remove(int index) {
        if (index > size - 1 || index < 0) {
            throw new IllegalArgumentException("Wrong index of element!");
        }

        Node<T> tmp = head;
        for (int i = 0; i < index - 1; i++) {
            tmp = tmp.next;
        }

        if (index == 0) {
            head = head.next;
        } else {
            tmp.next = tmp.next.next;
        }
        size--;
    }

    public void clear() {
        for (int i = 0; i < size; i++) {
            head.next = null;
        }
        head = null;
        size = 0;
    }

    public boolean contains(T value) {
        Node<T> tmp = head;
        for (int i = 0; i < size; i++) {
            if (value == tmp.value) {
                return true;
            }
            tmp = tmp.next;
        }
        return false;
    }

    private class Node<T> {
        Node<T> next;
        T value;

        Node(Node<T> next, T value) {
            this.next = next;
            this.value = value;
        }
    }

    @Override
    public Iterator<T> iterator() {
        return new SimpleListIterator<T>(head);
    }

    private class SimpleListIterator<T> implements Iterator<T> {
        private Node<T> head;
        private int counter;

        SimpleListIterator(Node<T> head) {
            this.head = head;
        }

        public boolean hasNext() {
            return head.next != null;
        }

        public T next() {
            if (counter == 0) {
                T tmp = head.value;
                counter++;
                return tmp;
            } else {
                head = head.next;
                return head.value;
            }
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();
        }
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        Node<T> tmp = head;

        for (int i = 0; i < size; i++) {
            sb.append(tmp.value + " ");
            tmp = tmp.next;
        }

        return sb.toString();
    }
}